package game;

import com.msg.MsgGame;
import com.msg.MsgMain;
import game.action.ActionBase;
import io.netty.channel.Channel;
import lombok.Data;
import net.NettyProtobufClient;
import net.message.MsgNotWritableCacheManager;
import net.message.MsgPack;
import net.message.MsgProcessor;
import util.ConfPropertiesUtil;
import util.LogUtil;

import java.lang.reflect.InvocationTargetException;
import java.util.LinkedList;
import java.util.List;

/**
 * 一个客户端实例
 */
@Data
public class Client {

    private int index;

    private String token;//唯一标识（debug登录账号）

    private NettyProtobufClient nettyProtobufClient = new NettyProtobufClient();

    private MsgProcessor msgProcess = new MsgProcessor();//仅处理本Client的协议

    private Channel channel = null;//netty链接

    private List<ActionBase> actionList = new LinkedList<>();//行为列表（按配置顺序）

    private boolean loginOK = false;//是否登录成功

    public Client(int index) {
        this.index = index;
        this.token = ConfPropertiesUtil.getInstance()._CLIENT_TOKEN_PREFIX + index;
    }

    public void Start() {
        //加载需要执行的action
        if (actionList.isEmpty()) {
            ClientManager.getInstance().getActionMap().forEach((k, v) -> {
                try {
                    actionList.add((ActionBase) v.getDeclaredConstructor().newInstance());
                } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
                         NoSuchMethodException e) {
                    LogUtil.game.error("Exception", e);
                }
            });
        }
        //连接服务器
        nettyProtobufClient.init(this);
    }

    public void close() {
        this.loginOK = false;
        if (null != this.channel) {
            this.channel.close();
        }
        this.nettyProtobufClient.close();
    }

    public void addMessagePack(MsgPack msgPack) {
        msgProcess.addMessagePack(msgPack);
    }

    /**
     * 建立链接成功
     */
    public void onChannelActive(Channel channel) {
        this.channel = channel;
        //先登录
        MsgMain.MainProtocl.Builder msg = MsgMain.MainProtocl.newBuilder();
        msg.setMessageType(MsgMain.MessageType.CS_Login);
        MsgGame.CSLogin.Builder msgData = MsgGame.CSLogin.newBuilder();
        msgData.setToken(getToken());
        msg.setCSLogin(msgData);
        sendMsg(msg);
    }

    public void process(long now) {
        msgProcess.process();
        actionList.forEach(v -> v.run(now, this));
    }

    /**
     * 发送信息
     */
    public boolean sendMsg(MsgMain.MainProtocl.Builder msg) {
        if (null == channel) {
            return false;
        }
        if (!channel.isActive()) {
            return false;
        }
        final int msgIndex = msg.getMessageType().getNumber();
        if (!channel.isWritable()) {
            MsgPack msgPack = new MsgPack(msgIndex, msg.build(), channel, this);
            MsgNotWritableCacheManager.getInstance().pushNotWritableMsg(msgPack);
            return false;
        }
        channel.writeAndFlush(msg.build());
        return true;
    }
}
